package com.xq.tmall.agu.timer;


import com.alibaba.excel.util.DateUtils;
import com.xq.tmall.entity.StockSector;
import com.xq.tmall.entity.WebPage;
import com.xq.tmall.service.StockSectorService;
import com.xq.tmall.util.DateUtil;
import com.xq.tmall.util.IpFerginUtil;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.xq.tmall.util.JsoupUitl;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jsoup.nodes.Document;
import org.jsoup.Jsoup;

@Component
@Slf4j
public class StockSectorTimer {

    private static final String URL = "https://push2.eastmoney.com/api/qt/clist/get";
    private static final int MAX_RETRIES = 3;
    private static final long BASE_DELAY_MS = 5000;
    private static final int PAGE_SIZE = 20; // 每页数据量
    private static final int TOTAL_PAGES = 22; // 总页数

    @Autowired
    private StockSectorService stockSectorService;
    @Autowired
    private IpFerginUtil ipFerginUtil;

    /**
     * 每天16:00执行板块数据更新
     */
    @Scheduled(cron = "0 37 15 * * ?")
    public void dailySectorUpdate() {
        log.info("开始执行板块数据更新任务...");
        LocalDateTime dateTime = LocalDateTime.now();
        // 周末不执行
        boolean isWeek = DateUtil.isWeekend(dateTime);
        if(isWeek){
            log.info("周末不执行");
            return;
        }
        ipFerginUtil.setRedisIp();
        // 检查当天是否已更新
        if (isTodayUpdated()) {
            log.info("今日板块数据已更新，跳过任务");
            return;
        }
        // 顺序处理所有页面
        for (int page = 1; page <= TOTAL_PAGES; page++) {
            boolean success = processPageWithRetry(page);

            if (!success) {
                log.error("第{}页数据处理失败，已达到最大重试次数", page);
                continue;
            }

            // 添加请求间隔，避免频繁请求
            try {
                Thread.sleep(30000); // 30秒间隔
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }

        log.info("板块数据更新任务完成");
    }

    private boolean isTodayUpdated() {
        Map<String, Object> params = new HashMap<>();
        params.put("historyDate", DateUtils.format(new Date(), "yyyy-MM-dd"));
        List<StockSector> sectorList = stockSectorService.findAllStockSectorInfo(params);
        return !sectorList.isEmpty();
    }

    public boolean processPageWithRetry(int page) {
        int attempt = 0;
        while (attempt < MAX_RETRIES) {
            try {
                Proxy proxy = new Proxy(Proxy.Type.HTTP,
                        new InetSocketAddress(ipFerginUtil.getRedisIp(),
                                Integer.parseInt(ipFerginUtil.getRedisPort())));

                log.info("处理第{}页数据，使用代理: {}:{}",
                        page, ipFerginUtil.getRedisIp(), ipFerginUtil.getRedisPort());

                Map<String, String> params = buildRequestParams(page);

                WebPage webPage = JsoupUitl.getWebPage(
                        URL,
                        Connection.Method.GET,
                        8000,
                        ipFerginUtil.getUseAgent(),
                        "https://quote.eastmoney.com/",
                        null,
                        proxy,
                        true,
                        null,
                        params
                );

                String bodyText = webPage.getDocument().body().text();
                String json = extractJsonp(bodyText);
                savePageData(page, json);
                return true;
            } catch (Exception e) {
                attempt++;
                log.warn("第{}页第{}次尝试失败: {}", page, attempt, e.getMessage());
                if (attempt < MAX_RETRIES) {
                    try {
                        // 指数退避延迟
                        long delay = (long) (BASE_DELAY_MS * Math.pow(2, attempt));
                        Thread.sleep(delay);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        return false;
                    }
                }
            }
        }
        return false;
    }

    private Map<String, String> buildRequestParams(int page) {
        Map<String, String> params = new HashMap<>();
        params.put("np", "1");
        params.put("fltt", "1");
        params.put("invt", "2");
        params.put("cb", "jQuery37108403873058354381_" + new Date().getTime());
        params.put("fs", "m:90+t:3+f:!50");
        params.put("fields", "f12,f13,f14,f1,f2,f4,f3,f152,f20,f8,f104,f105,f128,f140,f141,f207,f208,f209,f136,f222");
        params.put("fid", "f3");
        params.put("pz", String.valueOf(PAGE_SIZE));
        params.put("po", "1");
        params.put("dect", "1");
        params.put("ut", "fa5fd1943c7b386f172d6893dbfba10b");
        params.put("wbp2u", "4519325966461096|0|1|0|web_" + new Date().getTime());
        params.put("pn", String.valueOf(page));
        return params;
    }

    private static String extractJsonp(String html) {
        Document doc = Jsoup.parse(html);
        String bodyText = doc.body().text();

        int start = bodyText.indexOf("{");
        int end = bodyText.lastIndexOf("}");

        if (start == -1 || end == -1) {
            throw new IllegalArgumentException("Invalid JSONP format");
        }

        return bodyText.substring(start, end + 1);
    }

    public void savePageData(int page, String json) {
        stockSectorService.batchUpdate(json);
        log.info("成功保存第{}页数据", page);
    }
}
